package cn.edu.xmu.orderpayment.payment.util.paypattern;

import cn.edu.xmu.oomall.core.util.JacksonUtil;
import cn.edu.xmu.orderpayment.payment.microservice.service.AliPayService;
import cn.edu.xmu.orderpayment.payment.microservice.returnobj.AliPayReturnObject;
import cn.edu.xmu.orderpayment.payment.model.bo.Amount;
import cn.edu.xmu.orderpayment.payment.util.baseobject.*;
import cn.edu.xmu.orderpayment.payment.util.config.payconfigs.AliPayConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author zihan zhou
 * @date 2021/12/5
 */
@Component
public class AliPaymentPattern implements BasePaymentPattern {

    @Autowired
    private AliPayConfig aliPayConfig;
    @Autowired
    private AliPayService alipayService;
    @Override
    public DoPayInfo pay(String outTradeNo, Amount amount, String description) {

        Map<String ,Object> bizMap=new HashMap<>();
        bizMap.put("out_trade_no", outTradeNo);
        bizMap.put("total_amount", amount.getTotal());
        String biz_content= JacksonUtil.toJson(bizMap);
        AliPayReturnObject res= alipayService.gatewayDo(aliPayConfig.getAppId(),"alipay.trade.wap.pay",aliPayConfig.getFormat(),aliPayConfig.getCharset(),aliPayConfig.getSignType(),aliPayConfig.getSign(),LocalDateTime.now().toString(),aliPayConfig.getNotifyUrl(),biz_content);
        return res.getPayRetVo().createDoPayInfo();
    }

    @Override
    public PaymentInfo getPayment(String outTradeNo) {

        String biz_content="{\n" +
                "    \"out_trade_no\": "+ outTradeNo +"\n" +
                "}";

        AliPayReturnObject res= alipayService.gatewayDo(aliPayConfig.getAppId(),"alipay.trade.query",aliPayConfig.getFormat(),aliPayConfig.getCharset(),aliPayConfig.getSignType(),aliPayConfig.getSign(),LocalDateTime.now().toString(),aliPayConfig.getNotifyUrl(),biz_content);
        if(res!=null&&res.getPayQueryRetVo()!=null) {
            return res.getPayQueryRetVo().createPaymentInfo();
        }
        return null;
    }

    @Override
    public void closePayment(String outTradeNo) {

        String biz_content="{\n" +
                "    \"out_trade_no\": "+ outTradeNo +"\n" +
                "}";
        alipayService.gatewayDo(aliPayConfig.getAppId(),"alipay.trade.close",aliPayConfig.getFormat(),aliPayConfig.getCharset(),aliPayConfig.getSignType(),aliPayConfig.getSign(),LocalDateTime.now().toString(),aliPayConfig.getNotifyUrl(),biz_content);

    }

    @Override
    public void refund(Amount amount, String outTradeNo, String outRefundNo, String reason) {
        Map<String ,Object> bizMap=new HashMap<>();
        bizMap.put("out_trade_no", outTradeNo);
        bizMap.put("out_request_no", outRefundNo);
        bizMap.put("refund_amount", amount.getRefund());
        String biz_content= JacksonUtil.toJson(bizMap);
        alipayService.gatewayDo(aliPayConfig.getAppId(),"alipay.trade.refund",aliPayConfig.getFormat(),aliPayConfig.getCharset(),aliPayConfig.getSignType(),aliPayConfig.getSign(),LocalDateTime.now().toString(),aliPayConfig.getNotifyUrl(),biz_content);

    }

    @Override
    public RefundInfo getRefund(String outTradeNo, String outRefundNo) {

        Map<String ,Object> bizMap=new HashMap<>();
        bizMap.put("out_trade_no", outTradeNo);
        bizMap.put("out_request_no", outRefundNo);
        String biz_content= JacksonUtil.toJson(bizMap);

        AliPayReturnObject aliPayReturnObject = alipayService.gatewayDo(aliPayConfig.getAppId(),"alipay.trade.refund.query",aliPayConfig.getFormat(),aliPayConfig.getCharset(),aliPayConfig.getSignType(),aliPayConfig.getSign(),LocalDateTime.now().toString(),aliPayConfig.getNotifyUrl(),biz_content);
        if(aliPayReturnObject !=null&& aliPayReturnObject.getRefundQueryRetVo()!=null)
            return aliPayReturnObject.getRefundQueryRetVo().createRefundInfo();
        return null;
    }

    @Override
    public BillDownloadInfo getBillDownloadUrl(LocalDate billDate) {

        AliPayReturnObject aliPayReturnObject = alipayService.gatewayDo(aliPayConfig.getAppId(), "alipay.data.dataservice.bill.downloadurl.query", aliPayConfig.getFormat(), aliPayConfig.getCharset(), aliPayConfig.getSignType(), aliPayConfig.getSign(), "LocalDateTime.now().toString()", aliPayConfig.getNotifyUrl(), null);
        if(aliPayReturnObject ==null|| aliPayReturnObject.getDownloadUrlQueryRetVo()==null) {
            return null;
        }
        return new BillDownloadInfo(aliPayReturnObject.getDownloadUrlQueryRetVo().getBillDownloadUrl());
    }

    @Override
    public List<Transaction> getTransactionsFromCSV(String downloadUrl) {
        List<Transaction> transactions = new ArrayList<>();
        try {
            File file = new File(downloadUrl);
            if (file.exists()) {
                //支付宝账单是GBK编码
                InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file), "GBK");
                BufferedReader reader = new BufferedReader(inputStreamReader);
                String line = null;
                String regex = "\\d*[.]\\d*";
                Pattern p = Pattern.compile(regex);
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                while ((line = reader.readLine()) != null) {
                    String[] item = line.split(",");
                    if (item.length == 12) {
                        if (item[0].equals("账务流水号")) {
                            continue;
                        }
                        LocalDateTime transactionTime = LocalDateTime.parse(item[4],dateTimeFormatter);
                        Transaction.TransactionType transactionType = Transaction.TransactionType.REFUND;
                        Long amount = Long.valueOf(0);
                        Matcher matcherPay = p.matcher(item[6]);
                        Matcher matcherRefund = p.matcher(item[7]);
                        while (matcherPay.find()&&matcherRefund.find()) {
                            if (!"".equals(matcherPay.group())&&!"0.00".equals(matcherPay.group())) {
                                amount = Long.valueOf((long) (100 * Double.valueOf(matcherPay.group())));
                                transactionType = Transaction.TransactionType.PAY;
                            }
                            if (!"".equals(matcherRefund.group())&&!"0.00".equals(matcherRefund.group())) {
                                amount = Long.valueOf((long) (100 * Double.valueOf(matcherRefund.group())));
                            }
                        }
                        String tradeSn = item[1].trim();
                        String requestSn = item[2].trim();
                        Transaction transaction = new Transaction(tradeSn, requestSn, transactionTime, transactionType, amount);
                        transactions.add(transaction);
                    }
                }
            }
        }catch (Exception e){

        }
        return transactions;
    }
}
